Skip to content

chore(lint): fix 288 ruff errors + a hidden UnboundLocalError - #9

Merged
OneByJorah merged 4 commits into
masterfrom
hermes/2026-10-08-lint-cleanup
Oct 8, 2026
Merged

OneByJorah merged 4 commits into
masterfrom
hermes/2026-10-08-lint-cleanup

Conversation

@OneByJorah

Copy link
Copy Markdown
Owner

Problem

The repo configures ruff (select = ["E","F","W","I","UP","B","SIM"]) but failed it
288 times, so lint output was noise nobody could act on — and a genuine bug was
hiding in it.

The real bug found

F823 — backend/services/netmiko_client.py

A redundant import re inside pull_running_config() made re a function-local
name, so the re.search(...) call above it raised:

UnboundLocalError: cannot access local variable 're' where it is not associated with a value

This is on the Cisco IOS version/SN parsing path of a config pull. Removed the local
import; the module-level import re is correct and already present.

Changes

  • All safe autofixes, plus hand edits for: E741×5, F841×3, SIM105×8, SIM108×2,
    E701×2, B007, F401, F404, I001, UP006/035/037/041/045, F541, E402, B024.
  • B008 (47×) moved to ignore, with a comment: FastAPI requires Depends() /
    File() / Query() to be called in argument defaults. That is the documented
    dependency-injection idiom, not a defect — "fixing" it would break the API.
  • B024 (SerialConnection(ABC) has no abstract members): it is a runtime-selected
    marker base, so adding a fabricated @abstractmethod would be wrong. Explicit noqa
    with the rationale instead.
  • security_auditor._check_aaa_config: the nested conditional was one unreadable
    line. Extracted into a named variable.

Verification (real commands)

Check Before After
ruff check . 288 errors All checks passed
pytest tests/ -q 11 passed 11 passed
import main — 67 routes
whole tree py_compile — 0 syntax errors
gitleaks clean clean

The security_auditor rewrite was behaviour-checked directly, not just linted —

input "no local fallback" findings
aaa authentication login default radius (bad) 1
aaa authentication login default radius local (good) 0
no aaa line at all 0
local on a different aaa line 0

Base branch

This stacks on hermes/2026-10-08-fix-backend-startup (PR #8) — it depends on that
branch's config.py fix. Merge #8 first, or retarget this PR after it lands.

Publishing mode is draft: review only, nothing released.

openhands-agent and others added 4 commits October 7, 2026 09:11
The backend could not start at all. Fixes four defects that each block import
or execution:

1. backend/config.py - Settings no longer defined OPENAI_API_KEY / OPENAI_MODEL,
   but the validation block read settings.OPENAI_API_KEY, raising
   AttributeError: 'Settings' object has no attribute 'OPENAI_API_KEY' at import.
   Regression introduced by 5e43b24, which deleted the two field definitions and
   in the same commit added the validation that reads them. Restored both fields.

2. backend/routers/chat.py:18 - docstring indented 8 spaces inside a 4-space
   function body -> IndentationError, blocking main.py.

3. scripts/cli.py:151 - string literal split across real newlines ->
   SyntaxError: unterminated string literal. Restored the \n escapes.

4. scripts/nethermind.py - main() read global API_BASE (line 251) before its
   global declaration (line 329) -> SyntaxError. Moved the declaration to the
   top of main().

Verified: import main -> OK with 67 routes; uvicorn serves / , /api/switches/,
/api/dashboard/stats, /docs, /openapi.json all 200; scripts/nethermind.py --help
runs; full tree compiles with 0 syntax errors.
The repo declared pytest config (testpaths=["tests"], python_files=["test_*.py"])
but shipped no tests — tests/ contained only a mock_switch.py helper.

- tests/conftest.py — puts backend/ on sys.path and redirects DATABASE_URL to a
  temporary sqlite file *before* main is imported, so the real switches.db is
  never touched. Tests use a per-test TestClient fixture.
- tests/test_api.py — 11 tests: app metadata, OpenAPI route presence, dashboard
  stats shape, switch list/create/read-back, dashboard count reflects a created
  switch, and 5 pure-logic unit tests of the ArubaOS/ProCurve running-config
  parser (scalars, role detection, services, VLAN block parsing, empty input).
- frontend/package-lock.json — npm synced the stale package name "nethermind"
  to "netcore" while building; matches package.json.

Verified: cd . && .venv/bin/python -m pytest tests/ -q -> 11 passed.
DB isolation verified by mtime (real switches.db untouched). ruff clean on both
new files. gitleaks clean.
Repo configured ruff (E,F,W,I,UP,B,SIM) but failed it 288 times, so lint was
noise nobody could act on. Now: ruff check . -> All checks passed.

Highlights:
- F823 (REAL BUG) backend/services/netmiko_client.py: a redundant local
  'import re' inside pull_running_config made 're' function-local, so the
  re.search() call above it raised UnboundLocalError. Removed the local import.
- E741 x5, F841 x3, SIM105 x8, SIM108 x2, E701 x2, B007, F401, F404, I001,
  UP006/035/037/041/045, F541, E402, B024: applied safe autofixes and hand
  edits. B008 (47x) is added to ignore: FastAPI requires Depends()/File()/
  Query() in argument defaults -- that is the documented DI idiom, not a bug.
- security_auditor._check_aaa_config: extracted the tangled inline conditional
  into a named variable. Behaviour verified unchanged by direct test:
  reports the missing-local-fallback finding only when 'aaa authentication
  login' is present without 'local' (1 for the bad case, 0 for the good case).
- B024: SerialConnection is a runtime-selected marker base, so an explicit
  noqa with rationale rather than adding a wrong @AbstractMethod.

Verified: ruff clean; 11 tests pass; import main -> 67 routes; whole tree
compiles; gitleaks clean.
@OneByJorah
OneByJorah changed the base branch from hermes/2026-10-08-fix-backend-startup to master October 8, 2026 22:13
@OneByJorah OneByJorah closed this Oct 8, 2026
@OneByJorah OneByJorah reopened this Oct 8, 2026
@OneByJorah
OneByJorah merged commit ac255d7 into master Oct 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants